Fully reset the xenstore connection when a domain is (re)introduced to xenstored.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 1 Mar 2007 14:51:12 +0000 (14:51 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Thu, 1 Mar 2007 14:51:12 +0000 (14:51 +0000)
Signed-off-by: Keir Fraser <keir@xensource.com>
tools/xenstore/xenstored_domain.c
tools/xenstore/xenstored_transaction.c
tools/xenstore/xenstored_transaction.h
tools/xenstore/xenstored_watch.c
tools/xenstore/xenstored_watch.h

index ba3507fdfc3a549a80dded621e835a58bfccc52e..5249ef6d56e1b86d4c395212bfefc9ad22b5eeac 100644 (file)
@@ -28,6 +28,7 @@
 #include "talloc.h"
 #include "xenstored_core.h"
 #include "xenstored_domain.h"
+#include "xenstored_transaction.h"
 #include "xenstored_watch.h"
 #include "xenstored_test.h"
 
@@ -289,6 +290,26 @@ static struct domain *find_domain_by_domid(unsigned int domid)
        return NULL;
 }
 
+static void domain_conn_reset(struct domain *domain)
+{
+       struct connection *conn = domain->conn;
+       struct buffered_data *out;
+
+       conn_delete_all_watches(conn);
+       conn_delete_all_transactions(conn);
+
+       while ((out = list_top(&conn->out_list, struct buffered_data, list))) {
+               list_del(&out->list);
+               talloc_free(out);
+       }
+
+       talloc_free(conn->in->buffer);
+       memset(conn->in, 0, sizeof(*conn->in));
+       conn->in->inhdr = true;
+
+       domain->interface->req_cons = domain->interface->req_prod = 0;
+       domain->interface->rsp_cons = domain->interface->rsp_prod = 0;
+}
 
 /* domid, mfn, evtchn, path */
 void do_introduce(struct connection *conn, struct buffered_data *in)
@@ -342,7 +363,7 @@ void do_introduce(struct connection *conn, struct buffered_data *in)
                talloc_steal(domain->conn, domain);
 
                fire_watches(conn, "@introduceDomain", false);
-       } else if (domain->mfn == mfn) {
+       } else if ((domain->mfn == mfn) && (domain->conn != conn)) {
                /* Use XS_INTRODUCE for recreating the xenbus event-channel. */
                if (domain->port)
                        xc_evtchn_unbind(xce_handle, domain->port);
@@ -354,9 +375,7 @@ void do_introduce(struct connection *conn, struct buffered_data *in)
                return;
        }
 
-       /* Rings must be quiesced. */
-       domain->interface->req_cons = domain->interface->req_prod = 0;
-       domain->interface->rsp_cons = domain->interface->rsp_prod = 0;
+       domain_conn_reset(domain);
 
        send_ack(conn, XS_INTRODUCE);
 }
index 69cc520bb976e487e769d6d28d95084712752104..cf10ecc34867ebff1ebd7dc6a51fd8533b2d3a2d 100644 (file)
@@ -23,6 +23,7 @@
 #include <sys/wait.h>
 #include <sys/time.h>
 #include <time.h>
+#include <assert.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <fcntl.h>
@@ -211,6 +212,21 @@ void do_transaction_end(struct connection *conn, const char *arg)
        send_ack(conn, XS_TRANSACTION_END);
 }
 
+void conn_delete_all_transactions(struct connection *conn)
+{
+       struct transaction *trans;
+
+       while ((trans = list_top(&conn->transaction_list,
+                                struct transaction, list))) {
+               list_del(&trans->list);
+               talloc_free(trans);
+       }
+
+       assert(conn->transaction == NULL);
+
+       conn->transaction_started = 0;
+}
+
 /*
  * Local variables:
  *  c-file-style: "linux"
index 1fc30dff503199da22e014a8fb275e4a8f7f66cf..ecbae47f2d6fb4f479ecfdfb6bc20985750ec8e9 100644 (file)
@@ -33,4 +33,7 @@ void add_change_node(struct transaction *trans, const char *node,
 
 /* Return tdb context to use for this connection. */
 TDB_CONTEXT *tdb_transaction_context(struct transaction *trans);
+
+void conn_delete_all_transactions(struct connection *conn);
+
 #endif /* _XENSTORED_TRANSACTION_H */
index 3de6e7ace8be366660adf505d2c866e6cc8a1e3e..4d1a6d5bfb647320049b72acf69cfc4366a257b6 100644 (file)
@@ -185,6 +185,17 @@ void do_unwatch(struct connection *conn, struct buffered_data *in)
        send_error(conn, ENOENT);
 }
 
+void conn_delete_all_watches(struct connection *conn)
+{
+       struct watch *watch;
+
+       while ((watch = list_top(&conn->watches, struct watch, list))) {
+               list_del(&watch->list);
+               talloc_free(watch);
+               domain_watch_dec(conn);
+       }
+}
+
 #ifdef TESTING
 void dump_watches(struct connection *conn)
 {
index 2eccff94766bb265483298bd30555cf9ca03b002..6125ff3886fb30e1a4b72e1e6f401640bf1abc7b 100644 (file)
@@ -30,4 +30,6 @@ void fire_watches(struct connection *conn, const char *name, bool recurse);
 
 void dump_watches(struct connection *conn);
 
+void conn_delete_all_watches(struct connection *conn);
+
 #endif /* _XENSTORED_WATCH_H */